package com.coolw.core.reflect;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * ReflectTest
 * <p>反射
 * <pre>
 *  它允许程序在运行时查询、访问和修改类、接口、字段和方法的信息。反射提供了一种动态操作类的能力，
 *  反射在很多框架中被广泛运用
 * </pre>
 *
 * <p>常用的反射API
 * <ul>
 *     <li>java.lang.Class: 表示类的Class对象。提供了方法来获取类的字段、方法、构造函数等</li>
 *     <li>java.lang.reflect.Field: 表示类的属性（字段）。提供了访问和修改字段的能力</li>
 *     <li>java，lang.reflect.Method: 表示类的方法。提供了调用方法的能力</li>
 *     <li>java.lang.reflect.Constructor: 表示类的构造函数。提供了创建对象的能力</li>
 * </ul>
 *
 * @author coolw
 * @date 2025/4/17 20:00
 */
public class ReflectTest {

    public static void main(String[] args) throws Exception {
        // 获取 Class 对象的方式
        //testClazz();

        // 获取 Class 对象
        Class<Person> clazz = Person.class;

        // 获取类的所有实现接口
        Class<?>[] interfaces = clazz.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println("Interface: " + anInterface.getName());
        }

        // 获取类的父类
        Class<? super Person> superClass = clazz.getSuperclass();
        System.out.println("superClass: " + superClass.getName());

        // 创建对象
        Constructor<Person> constructor = clazz.getConstructor(String.class, Integer.class);
        Person person = constructor.newInstance("coolw", 20);

        // 访问字段
        Field nameField = clazz.getDeclaredField("name");
        // 如果字段是私有的,则需要设置可访问,否则会报 IllegalAccessException 异常
        nameField.setAccessible(true);
        Object nameVal = nameField.get(person);
        System.out.println("name: " + nameVal);

        // 修改字段
        nameField.set(person, "lisi");
        System.out.println("name: " + nameField.get(person));

        // 调用方法
        Method method = clazz.getMethod("say", String.class);
        Object invoke = method.invoke(person, "你好!");
        System.out.println(invoke);
    }

    /**
     * 获取 Class 对象的方式有三种
     * 1.通过类
     * 2.通过对象实例
     * 3.通过Class.forName()方法
     */
    private static void testClazz() throws ClassNotFoundException {
        // 通过类获取
        Class<String> clazz1 = String.class;
        System.out.println("clazz1: " + clazz1.getName());

        // 通过对象实例获取
        String str = "hello";
        Class<? extends String> clazz2 = str.getClass();
        System.out.println("clazz2: " + clazz2.getName());

        // 通过Class.forName()方法获取
        Class<?> clazz3 = Class.forName("java.lang.String");
        System.out.println("clazz3: " + clazz3.getName());
    }

    static class Person implements Serializable {
        private static final long serialVersionUID = 99770740110608705L;

        private final String name;
        private final Integer age;

        public Person(String name, Integer age) {
            this.name = name;
            this.age = age;
        }

        public String say(String message) {
            return name + " say: " + message;
        }
    }
}
